//
//  Game.cpp
//  Dungeons and Princesses
//
//  Created by phuong on 10/15/11.
//*Updated Nov 5, 2011 - River Warren
//  Copyright (c) 2011 SD Networks. All rights reserved.
//
//  Updated many changes to include new methods for parsing commands from interface class

#include <iostream>

#include "Game.h"
#include "TextInterface.h"
#include "NTextInterface.h"
#include "Utility.h"
#include "Direction.h"
#include "Inventory.h"
#include "Key.h"
#include "Potion.h"
#include "EquipmentType.h"
#include "PlayerStats.h"
#include "Monster.h"
#include "Attack.h"
#include <string>
#include <sstream>
#include <fstream>

//using namespace std;

Game::Game() {

    myInterface = new TextInterface(this);
    currentRoom = new Room();
    currentPlayer = new Player();
    // decide if this is a new game or not
    int gameNumber;
    if((gameNumber = myInterface->loadGame()) >= 0){
        loadSavedGame(gameNumber);
    }
    else {
        initGame();
    }


}

Castle * Game::getCastle() {

    return gameCastle;
}

Room * Game::getCurrentRoom() {

    return currentRoom;
}

Player * Game::getCurrentPlayer() {

    return currentPlayer;
}

void Game::setCurrentRoom(Room *newRoom) {

    currentRoom = newRoom;
}

vector<std::string> * Game::loadHelp() {

    std::vector<std::string> * helpFile = new std::vector<std::string>;
    std::string path = Utility::getCurrentWorkingDir() + "/Docs/help.txt";
    std::string tmp;
    ifstream in(path.c_str());
    if(!in.eof()){
	while(!in.eof()){
		getline(in,tmp);
		helpFile->push_back(tmp);
	}
    }
    return helpFile;
}

void Game::run() {


    myInterface->loadInterface();

}

// initialize a new game
void Game::initGame() {

    Utility::initSeed();
    try
    {
        gameCastle = new Castle(Utility::getCurrentWorkingDir() + "/Data");
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    currentRoom = gameCastle->getRoom("R0");

    currentRoom->setVisited(); // set starting room to spawn no monsters

    Key *testKey = new Key("Rusty Key", "P1");

    gameCastle->addByRoom(0, testKey);
    
    Key *testkey2 = new Key("Bronze key", "P2");
    
    gameCastle->addByRoom(0, testkey2);
    
    LockableContainer *chest = new LockableContainer("Large chest", "L1");

    Potion *testPotion2 = new Potion();

    chest->add(testPotion2);

    Key *chestKey = new Key("Small key", "L1");//key for lockable container
    gameCastle->addByRoom(1, chestKey); //

    gameCastle->addByRoom(2, chest);

    Potion *minorHealth = new Potion(MINORH);
    gameCastle->addByRoom(0, minorHealth );

    EquipmentType *testEquipment = new EquipmentType();
    gameCastle->addByRoom(2, testEquipment);
    
    EquipmentType *head = new EquipmentType(HEAD);
    gameCastle->addByRoom(0, head);
    
    EquipmentType *chestplayer = new EquipmentType(CHEST);
    gameCastle->addByRoom(0, chestplayer);
    
    // todo: commented out spawning initial gloves and feet to make the game a little more challenging
   //EquipmentType *gloves = new EquipmentType(GLOVES);
   //gameCastle->addByRoom(0, gloves);
    
    //EquipmentType *feet = new EquipmentType(FEET);
    //gameCastle->addByRoom(0, feet);
    
    EquipmentType *pants = new EquipmentType(PANTS);
    gameCastle->addByRoom(0, pants);

    EquipmentType *weapon = new EquipmentType(WEAPON);
    gameCastle->addByRoom(0, weapon);


    Monster *monster1 = new Monster(1);

    gameCastle->addByRoom(2, monster1);

//    Monster *monster2 = new Monster(1);
//
//    gameCastle->addByRoom(2, monster2);


    myInterface->setupPlayer();

}
void Game::randomMonster()
{
    int num1 = Utility::getSeed(100);
    int num2 = Utility::getSeed(100);
    int num3 = Utility::getSeed(100);
    int num4 = Utility::getSeed(100);
    int num5 = Utility::getSeed(100);
    int numlevel = currentPlayer->getPlayerStats().getLevel();
    if (numlevel  >= 1 )
    {
        if (num1 >= 50 )
        {
            Monster *monster = new Monster(numlevel);
            currentRoom->add(monster);
        }
        if (num2 > 70)
        {
            Monster *monster = new Monster(numlevel);
            currentRoom->add(monster);
        }
        if (numlevel >= 2)
        {
            if (num3 > 60)
            {
                Monster *monster = new Monster(numlevel);
                currentRoom->add(monster);
            }
        }
        if (numlevel >= 3)
        {
            if (num4 > 70)
            {
                Monster *monster = new Monster(numlevel);
                currentRoom->add(monster);
            }
        }
        if (numlevel >= 4)
        {
            if (num5 > 80)
            {
                Monster *monster = new Monster(numlevel);
                currentRoom->add(monster);
            }
        }
    }

}

bool Game::setupPlayer(std::string playerName, std::string charClass, std::string &errorMSG){

    if (charClass == "warrior" || charClass == "1") {

        PlayerStats myStats = PlayerStats(WARRIOR);

        currentPlayer = new Player(playerName, WARRIOR, myStats);

        return true;
    }

    else if (charClass == "wizard" || charClass == "2") {

        PlayerStats myStats = PlayerStats(WIZARD);

        currentPlayer = new Player(playerName, WIZARD, myStats);

        return true;
    }

    else if (charClass == "ranger" || charClass == "3") {

        PlayerStats myStats = PlayerStats(RANGER);

        currentPlayer = new Player(playerName, RANGER, myStats);

        return true;

    }

    else {

        errorMSG = "Please try again, you need to enter a valid class";
        return false;
    }

}
void Game::testDelegate(std::string myStringToTest) {

    std::cout << myStringToTest << std::endl;

}


void Game::saveGame(string dir, bool newFile)
{
    string fileDir, playerFile;
    stringstream temp;
    try
    {
        fileDir = Utility::getCurrentWorkingDir() + '/' + dir;
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    temp << fileDir << '/' << currentPlayer->getObjectID() << ".plyr";
    playerFile = temp.str();
    try
    {
        gameCastle->saveRooms(fileDir);
        currentPlayer->savePlayer(playerFile);
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }

    string gameFile = fileDir + "/game.gme";
    ofstream out(gameFile.c_str());
    Base b;
    if(out.is_open())
    {
        out << playerFile << endl << b << endl << currentRoom->getLinkID();
    }
    else
    {
        string msg = "Error: File " + gameFile + " did not open.";
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    out.close();
    if(newFile)
    {
        string gameListFile;
        try
        {
            gameListFile = Utility::getCurrentWorkingDir() + "/Data/gameList.gml";
        }
        catch(string msg)
        {
            myInterface->printErrorMsg(msg);
            exit(1);
        }
        out.open(gameListFile.c_str(), ios_base::app);
        if(out.is_open())
        {
            out << dir << endl;
        }
        else
        {
            string msg = "Error: File " + gameListFile + " did not open.";
            myInterface->printErrorMsg(msg);
            exit(1);
        }
        out.close();

    }
    myInterface->printErrorMsg("You have successfully save the game " + dir + ".\nThank you for playing.");
}

void Game::loadSavedGame(int gameNumber)
{
    Player * p = new Player();
    bool isSavedGame;
    vector<string> gameList = getGameList(isSavedGame);
    string fileDir, playerFile;
    char data[MAX] = ""; //to hold line
    try
    {
        fileDir = Utility::getCurrentWorkingDir() + '/' + gameList.at(gameNumber);
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    string gameFile = fileDir + "/game.gme";
    ifstream in(gameFile.c_str());
    Base b;
    if(in.is_open())
    {
        in.getline(data,MAX - 1, '\n');
        playerFile = data;
        in >> b;
        in.ignore();
        in.getline(data,MAX - 1, '\n');
    }
    else
    {
        string msg = "Error: File " + gameFile + " did not open.";
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    in.close();
    try
    {
        gameCastle = new Castle(fileDir);
        currentRoom = gameCastle->getRoom(data);
        p->loadPlayer(playerFile);
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }

    currentPlayer = p;
}

vector<string> Game::getGameList(bool & isSavedGames)
{
    vector<string> gameList;
    string gameListFile;
    try
    {
        gameListFile = Utility::getCurrentWorkingDir() + "/Data/gameList.gml";
    }
    catch(string msg)
    {
        myInterface->printErrorMsg(msg);
        exit(1);
    }
    ifstream in(gameListFile.c_str());
    if(in.is_open())
    {
        char data[MAX] = ""; //to hold line
        while(in.getline(data,MAX - 1, '\n'))
        {
            gameList.push_back(data);
            isSavedGames = true;
        }
    }
    else
    {
        isSavedGames = false;
    }
    return gameList;
}
